package com.chunfeng.mypen.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chunfeng.mypen.auth.UserDetailEntity;
import com.chunfeng.mypen.dao.UserDao;
import com.chunfeng.mypen.entity.User;
import com.chunfeng.mypen.note.ExcludeMethods;
import com.chunfeng.mypen.properties.SystemProperties;
import com.chunfeng.mypen.result.JsonRequest;
import com.chunfeng.mypen.result.exception.ServiceException;
import com.chunfeng.mypen.result.exenum.RequestException;
import com.chunfeng.mypen.service.PermissionService;
import com.chunfeng.mypen.service.UserService;
import com.chunfeng.mypen.utils.RedisClientsUtils;
import com.chunfeng.mypen.utils.TokenUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 用户业务实现
 *
 * @author by 春风能解释
 * <p>
 * 2023/11/15
 */
@Service
@CacheConfig(cacheNames = "User_Table")
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService, UserDetailsService {

    /**
     * 用户Dao注入
     */
    @Autowired
    private UserDao userDao;

    /**
     * 权限业务层引入
     */
    @Autowired
    private PermissionService permissionService;

    /**
     * 密码加密类
     */
    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    /**
     * 身份验证对象
     */
    @Autowired
    private AuthenticationManager authenticationManager;

    /**
     * Redis工具类
     */
    @Autowired
    private RedisClientsUtils redisClientsUtils;
    /**
     * 系统配置
     */
    @Autowired
    private SystemProperties systemProperties;

    /**
     * 用户登录
     *
     * @param name     用户名
     * @param password 密码
     * @return JSON
     */
    @Override
    @ExcludeMethods
    public JsonRequest<String> login(String name, String password) {
        //获取UserDetail对象
        UsernamePasswordAuthenticationToken userToken = new UsernamePasswordAuthenticationToken(name, password);
        Authentication authenticate = authenticationManager.authenticate(userToken);
        //获取权限对象
        Object principal = authenticate.getPrincipal();
        //判空
        if (Objects.isNull(principal) || !(principal instanceof UserDetailEntity)) {
            return JsonRequest.error(RequestException.LOGIN_ERROR);
        }
        //转换为实际的用户权限对象
        UserDetailEntity userDetail = (UserDetailEntity) principal;
        //获取用户实际对象
        User user = userDetail.getUser();
        //生成token对象
        String token = TokenUtils.createToken(user.getId());
        //将用户信息存入Redis数据库
        redisClientsUtils.set(
                "login:" + user.getId(), //key: login:2(数字代表ID)
                JSON.toJSONString(userDetail));//value: 用户序列化后的字符串
        return JsonRequest.success(token);
    }

    /**
     * 用户注册
     *
     * @param name     用户名
     * @param password 密码
     * @return JSON
     */
    @Override
    @ExcludeMethods
    public JsonRequest<Integer> register(String name, String password) {
        User user = userDao.selectAllByName(name);
        //判断用户是否已经存在
        if (Objects.nonNull(user)) {
            return JsonRequest.error(RequestException.REGISTER_ERROR);
        }
        //新增用户
        int column = userDao.insert(
                new User(name,
                        bCryptPasswordEncoder.encode(password)));//密码加密
        //判断是否成功
        if (column < 1) {
            return JsonRequest.error(RequestException.REGISTER_ERROR);
        }
        return JsonRequest.success(column);
    }

    /**
     * 条件查询用户
     *
     * @param current 当前页
     * @param size    每页长度
     * @param user    条件
     * @return JSON
     */
    @Override
    @Cacheable(key = "#args")
    public JsonRequest<List<User>> lookAllUser(Integer current, Integer size, User user) {
        Page<User> userPage = userDao.selectAllUser(new Page<>(current, size), user);
        //拿到列表数据
        List<User> users = userPage.getRecords();
        if (users.isEmpty()) {
            return JsonRequest.error(RequestException.NOT_FOUND);
        }
        Map<String, Object> page = new HashMap<>();
        //存入总页数
        page.put(systemProperties.getPageKeyName(), userPage.getTotal());
        return JsonRequest.success(users, page);
    }

    /**
     * 查询用户个人信息
     *
     * @param id 用户ID
     * @return JSON
     */
    @Override
    @Cacheable(key = "#id")
    public JsonRequest<User> lookOneUser(String id) {
        User user = userDao.selectById(id);
        if (Objects.isNull(user)) {
            return JsonRequest.error(RequestException.NOT_FOUND);
        }
        return JsonRequest.success(user);
    }

    /**
     * 更新用户信息
     *
     * @param user 待更新的用户
     * @return JSON
     */
    @Override
    @CachePut
    public JsonRequest<Integer> updateOneUser(User user) {
        User user1 = userDao.selectById(user.getId());
        if (Objects.isNull(user1)) {
            return JsonRequest.error(RequestException.NOT_FOUND);
        }
        int column = userDao.updateById(user);
        if (column < 1) {
            return JsonRequest.error(RequestException.DELETE_ERROR);
        }
        return JsonRequest.success(column);
    }

    /**
     * 批量注销用户
     *
     * @param ids 用户ID
     * @return JSON
     */
    @Override
    @CacheEvict
    public JsonRequest<Integer> logoutUsers(List<String> ids) {
        Integer size = userDao.selectCountUser(ids);
        if (size != ids.size()) {
            return JsonRequest.error(RequestException.NOT_FOUND);
        }
        int column = userDao.deleteBatchIds(ids);
        if (column < 1) {
            return JsonRequest.error(RequestException.DELETE_ERROR);
        }
        return JsonRequest.success(column);
    }

    /**
     * 加载用户权限对象
     *
     * @param username 用户名
     * @return 用户权限对象
     * @throws UsernameNotFoundException 当传入的用户名不正确时
     */
    @Override
    @ExcludeMethods
    @Cacheable(key = "#username")
    public UserDetailEntity loadUserByUsername(String username) throws UsernameNotFoundException {
        //根据用户名查询用户信息是否存在
        User user = userDao.selectAllByName(username);
        //如果结果为空
        if (Objects.isNull(user)) {
            throw new ServiceException(RequestException.LOGIN_ERROR);
        }
        UserDetailEntity userDetail = new UserDetailEntity();
        //设置用户信息
        userDetail.setUser(user);
        //静态权限
        userDetail.setPermissionList(Arrays.asList("1", "2"));
        /*// 动态权限
        //拿到权限列表
        JsonRequest<List<Permission>> request = permissionService
                .lookPermissionOfOneUser(user.getId());
        //报错
        if (!request.getSuccess()) {
            throw new ServiceException(RequestException.LOGIN_ERROR);
        }
        List<Permission> permissions = request.getData();
        //权限的三个字段=>xx:xx:xx
        List<String> permissionSigns = permissions.stream()
                .map(permission -> String.format("%s:%s:%s",
                        permission.getRegion(),//范围
                        permission.getEntity(),//实体
                        permission.getOption()))//操作
                .collect(Collectors.toList());
        //将权限列表导入用户权限对象
        userDetail.setPermissionList(permissionSigns);*/
        return userDetail;
    }
}
